package server;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;

public class IDInstance 
{
	private IDFile myRoot = null;
	
	public static enum FileTypes
	{
		Folder,
		Unknown,
		Text,
		Image,
		Audio,
		Video,
		Archive,
		Executable
	}
	
	public static class IDFile
	{
		public File file;
		public String name;
		public String absPath;
		public String relPath;
		public FileTypes type;
		public long size;
		public boolean dir;
		public ArrayList<IDFile> children = null;
		public IDFile parent = null;
		public Date date = null;
	}
	
	public IDInstance(String path, boolean includeHidden)
	{
		myRoot = parsePath(path, path, includeHidden);
	}
	
	public IDFile getRoot()
	{
		return myRoot;
	}
	
	public boolean isSingleFile()
	{
		if(myRoot != null)
		{
			return !myRoot.dir;
		}
		else
		{
			return false;
		}
	}
	
	private static String constructRelPath(String base, String target)
	{
		if(base.equals(target))
			return "";
		
		if(base.length() > target.length())
			return File.separator;
		
		return target.substring(base.length(), target.length()).replace('\\', '/');
	}
	
	private static FileTypes guessFileType(String name)
	{
		final String[] extText = { "txt", "nfo", "bat", "log", "sh", "doc", "docx", "odt", "pdf", 
				"c", "cpp", "h", "java", "py", "php", "html", "js", "css" };
		final String[] extImage = { "jpg", "jpeg", "gif", "png", "bmp", "tga", "psd", "xcf", "svg" };
		final String[] extAudio = { "wav", "mid", "midi", "mp3", "m4a", "aac", "dts", "wma", "ogg", "oga" };
		final String[] extVideo = { "avi", "mpeg", "mp4", "mkv", "asf", "wmv", "bik", "ogv", "webm", "divx" };
		final String[] extArchive = { "zip", "rar", "7z", "tar", "gz", "bz2", "arj", "xz" };
		final String[] extExec = { "exe", "com", "scr", "deb", "msi", "run", "bin" };
		
		if(!name.contains(".")) return FileTypes.Unknown;
		name = name.toLowerCase();
		for(int i = name.length() - 1; i > 0; --i)
		{
			if(name.charAt(i) == '.')
			{
				String ext = name.substring(i + 1, name.length());
				//System.out.println("Extension is '" + ext + "'");
				if(Arrays.asList(extText).contains(ext))
					return FileTypes.Text;
				else if(Arrays.asList(extImage).contains(ext))
					return FileTypes.Image;
				else if(Arrays.asList(extAudio).contains(ext))
					return FileTypes.Audio;
				else if(Arrays.asList(extVideo).contains(ext))
					return FileTypes.Video;
				else if(Arrays.asList(extArchive).contains(ext))
					return FileTypes.Archive;
				else if(Arrays.asList(extExec).contains(ext))
					return FileTypes.Executable;
				else
					return FileTypes.Unknown;
			}
		}
		
		return FileTypes.Unknown;
	}
	
	private IDFile parsePath(String basePath, String path, boolean hidden)
	{
		File info = new File(path);
		if(!info.exists())
			return null;
		
		if(!hidden && info.getName().startsWith("."))
			return null;
		
		IDFile file = new IDFile();
		
		file.file = info;
		file.name = info.getName();
		file.absPath = info.getAbsolutePath();
		file.relPath = constructRelPath(basePath, file.absPath);
		
		if(info.isDirectory())
		{
			file.dir = true;
			file.children = new ArrayList<IDInstance.IDFile>();
			file.type = FileTypes.Folder;
			
			File[] children = info.listFiles();
			for(File f : children)
			{
				IDFile idf = parsePath(basePath, f.getAbsolutePath(), hidden);
				if(idf != null)
				{
					idf.parent = file;
					file.children.add(idf);
				}
			}
			Collections.sort(file.children, new Comparator<IDFile>() 
			{

				@Override
				public int compare(IDFile o1, IDFile o2) 
				{
					if(o1.dir && !o2.dir)
						return -1;
					if(!o1.dir && o2.dir)
						return 1;
					return o1.name.compareTo(o2.name);
				}
			});
			
			file.date = new Date(info.lastModified());
			file.size = file.children.size();
		}
		else
		{
			file.dir = false;
			file.type = guessFileType(file.name);
			file.size = info.length();
			file.date = new Date(info.lastModified());
		}
		
		//System.out.println(file.relPath + " (" + file.type.toString() + ")");
		
		return file;
	}
	
	public IDFile traversePath(String path)
	{
		if(path.length() == 0)
			return myRoot;
		
		if(path.length() > 1)
		{
			while(path.startsWith("/"))
				path = path.substring(1, path.length());
		}
		
		String[] parts = path.split("[/\\\\]");
		IDFile pos = myRoot;
		for(String part : parts)
		{
			boolean found = false;
			for(IDFile child : pos.children)
			{
				if(child.name.equals(part))
				{
					pos = child;
					found = true;
					break;
				}
			}
			if(!found)
			{
				System.out.println("Path \"" + path + "\" lost at \"" + part + "\"");
				return null;
			}
		}
		return pos;
	}
}
